package com.sunrise.gateway.commons;

import com.alibaba.fastjson.JSON;
import com.dap.exception.BusinessException;
import com.dap.exception.PlatformException;
import com.dap.param.StringInput;
import com.google.common.base.Charsets;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.mail.internet.MimeUtility;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.URLEncoder;

public abstract class CommonUtils {
    private final static Logger logger = LoggerFactory.getLogger(CommonUtils.class);

    public static String inputStream2String(InputStream is) throws IOException,PlatformException {
        byte[] bytes = GatewayByteBufferUtils.getByteBufferFromPool();

        int offset = 0;

        try {
            while (true) {
                int readCount = is.read(bytes, offset, bytes.length - offset);

                if (readCount == -1) {
                    return new String(bytes, 0, offset);
                }

                offset += readCount;
                if (offset == bytes.length) {
                    logger.info("{}", new String(bytes));
                    throw new PlatformException("content to long");
                }
            }
        } finally {
            GatewayByteBufferUtils.releaseByteBufferToPool(bytes);
        }
    }

    public static StringInput parseRequestStringInput(HttpServletRequest req) throws PlatformException {
        String str;
        try {
            str = inputStream2String(req.getInputStream());
        } catch (IOException e) {
            throw new PlatformException("获取数据流失败, uri="+req.getRequestURI(), e);
        }

        try {
            StringInput stringInput = JSON.parseObject(str, StringInput.class);
            stringInput.setCtrlData(stringInput.getCtrlData().buildAttributesOnlyFromFrontend());
            return stringInput;
        } catch (Exception e) {
            throw new PlatformException("json类型转换失败, uri="+req.getRequestURI()+", 内容="+str, e);
        }
    }


    /****
     * 根据req获取组名
     * @param req
     * @return
     */
    public static String getGroup(HttpServletRequest req) {
        String uri = getURIWithoutContextPath(req);
        return uri.replace('/', '.').substring(1);
    }

    /****
     * 根据req获取uri的值
     * @param req
     * @return
     */
    public static String getURIWithoutContextPath(HttpServletRequest req) {
        String uri = req.getRequestURI();
        String contextPath = req.getContextPath();
        String result = uri.substring(contextPath.length());

        int idx = result.indexOf(';');
        if (idx >= 0)
            result = result.substring(0, idx);
        idx = result.indexOf('?');
        if (idx >= 0)
            result = result.substring(0, idx);

        return result;
    }


    public static String getRemoteAddrIp(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("WL-Proxy-Client-IP");
                if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                    ip = request.getRemoteAddr();
                    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                        return null;
                    }
                }
            }
        }

        int firstIdx = ip.indexOf(",");
        if (firstIdx > 0) {
            ip = ip.substring(0, firstIdx);
        }
        return ip;
    }


    public static String generateDispositionFileName(String fileName, String userAgent) {
        try {
            String urlFileName = URLEncoder.encode(fileName, "UTF-8");

            if (userAgent != null) {
                userAgent = userAgent.toLowerCase();

                // ie浏览器, edge浏览器
                if (-1 != userAgent.indexOf("msie") || -1 != userAgent.indexOf("trident") || -1 != userAgent.indexOf("edge")) {
                    //处理IE文件名空格变成"+"的问题
                    urlFileName = urlFileName.replace("+", "%20");
                    return "filename=\"" + urlFileName + "\"";
                }
                // Opera浏览器只能采用filename*
                else if (userAgent.indexOf("opera") != -1) {
                    return "filename*=UTF-8''" + urlFileName;
                }
                // Safari浏览器，只能采用ISO编码的中文输出
                else if (userAgent.indexOf("safari") != -1) {
                    return "filename=\"" + new String(fileName.getBytes(Charsets.UTF_8), "ISO8859-1") + "\"";
                }
                // Chrome浏览器，只能采用MimeUtility编码或ISO编码的中文输出
                else if (userAgent.indexOf("applewebkit") != -1) {
                    urlFileName = MimeUtility.encodeText(fileName, "UTF-8", "B");
                    return "filename=\"" + urlFileName + "\"";
                }
                // FireFox浏览器，可以使用MimeUtility或filename*或ISO编码的中文输出
                else if (userAgent.indexOf("mozilla") != -1) {
                    return "filename*=UTF-8''" + urlFileName;
                }
            }

            // 如果没有UserAgent，则默认使用IE的方式进行编码，因为毕竟IE还是占多数的
            return "filename=\"" + urlFileName + "\"";
        } catch (Exception e) {
            return "default";
        }
    }


    // 将对象转换成json字符串, 并写入servlet输出流
    public static void writeStrIntoResponse(String str, HttpServletResponse resp) {
        PrintWriter out = null;
        try {
            resp.setCharacterEncoding("UTF-8");
            resp.setHeader("Content-Type", "application/json");

            out = resp.getWriter();
            out.print(str);
            out.flush();
        } catch (IOException e) {
            logger.warn("", e);
            throw new PlatformException("返回结果异常");
        } finally {
            if (out != null) {
                out.close();
            }
        }
    }


    public static Result handleServletException(Exception e) {
        // 网关打印日志
        logger.error("", e);


        /**业务异常**/
        if (e instanceof BusinessException) {
            return handleBusinessException((BusinessException) e);
        }
        /**用户无权限异常扩展**/
        else if (e instanceof IllegalArgumentException && e.getMessage().contains("Wildcard string cannot be null or empty")) {
            return new Result(Constants.USER_ILLEGAL, "用户无权限", null);
        }
        // 参数验证异常
        else if (e instanceof com.dap.exception.IllegalArgumentException) {
            return new Result(((PlatformException) e).getErrorCode(), ((PlatformException) e).getErrorMessage(), null);
        }
        /**其他系统类异常**/
        else {
            // 找到根异常
            while (e.getCause() != null) {
                if (e == e.getCause()) {
                    break;
                }
                e = (Exception) e.getCause();
                if (e instanceof BusinessException) {
                    break;
                }
            }

            /**业务系统循环调用内部发生的业务异常**/
            if (e instanceof BusinessException) {
                return handleBusinessException((BusinessException) e);
            }
            /**系统非法数据异常,业务系统入参校验**/
            else if (e instanceof com.dap.exception.IllegalArgumentException) {
                String message = ((PlatformException) e).getErrorMessage();
                if (StringUtils.isEmpty(message)) {
                    message = "业务异常";
                }
                return new Result(((PlatformException) e).getErrorCode(), message, null);
            }
            /**session过期异常**/
            else if (e instanceof org.apache.shiro.session.StoppedSessionException) {
                return new Result(Constants.USER_SESSION_INVALID, "登录过期异常", null);
            } else {
                return new Result(com.dap.commons.Constants.ResponseCode.SYS_ERROR, "系统异常", null);
            }
        }

        //return new Result(com.dap.commons.Constants.ResponseCode.SYS_ERROR, "系统异常", null);
    }
    private static Result handleBusinessException(BusinessException e) {
        String message = e.getErrorMessage();
        if (StringUtils.isEmpty(message)) {
            message = "业务异常";
        }
        return new Result(e.getErrorCode(), message, e.getExtraObject());
    }


    public static String resolveDomain(HttpServletRequest req) {
        String host = req.getHeader("Host");

        int colonIdx = host.indexOf(':');
        if (colonIdx >= 0) {
            return host.substring(0, colonIdx);
        } else {
            return host;
        }
    }

    public static void clearCookies(HttpServletRequest req, HttpServletResponse resp) {
        final String domain = CommonUtils.resolveDomain(req);

        Cookie[] oldCookies = req.getCookies();
        if (null == oldCookies || oldCookies.length <= 0) {
            return;
        }

        for (Cookie oldCookie : oldCookies) {
            Cookie cookie = new Cookie(oldCookie.getName(), "deleteMe");
            cookie.setMaxAge(0);
            cookie.setPath("/");
            cookie.setDomain(domain);
            cookie.setVersion(oldCookie.getVersion());
            resp.addCookie(cookie);
        }
    }

}
